package com.gzxx.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.gzxx.constant.ServiceCodeStatus;
import com.gzxx.constant.SystemConstant;
import com.gzxx.domain.base.BaseVo;
import com.gzxx.domain.base.RequestPage;
import com.gzxx.domain.bo.SysUserBO;
import com.gzxx.domain.po.SysUser;
import com.gzxx.domain.vo.SysDeptVo;
import com.gzxx.domain.vo.SysRoleVo;
import com.gzxx.domain.vo.SysUserVo;
import com.gzxx.domain.vo.UserDeptDetailVo;
import com.gzxx.exception.ServiceException;
import com.gzxx.mapper.SysUserDeptMapper;
import com.gzxx.mapper.SysUserMapper;
import com.gzxx.mapper.SysUserRoleMapper;
import com.gzxx.security.CurrentUser;
import com.gzxx.service.*;
import com.gzxx.util.ServerResponse;
import com.gzxx.util.SysLoginUserHelper;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import java.lang.reflect.InvocationTargetException;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author MAX
 * @date 2020/7/23 10:42 上午
 * 系统用户业务接口实现类
 */

@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
@Transactional(readOnly = true, rollbackFor = Exception.class, timeout = 5)
public class SysUserServiceImpl implements SysUserService {

    private final SysUserMapper sysUserMapper;
    private final SysUserRoleMapper sysUserRoleMapper;

    private final SysRoleService sysRoleService;
    private final SysUserRoleService sysUserRoleService;
    private final SysDeptService sysDeptService;
    private final SysUserDeptService sysUserDeptService;
    private final SysUserDeptMapper sysUserDeptMapper;

    /**
     * 系统用户信息分页查询
     */
    @Override
    public IPage<SysUserVo> users(SysUserBO sysUserBO) {
        try {
            Map<?, ?> queryParams = sysUserBO.queryParams();
            RequestPage requestPage = sysUserBO.getPage();
            Page<SysUserVo> page = new Page<SysUserVo>(requestPage.getPage(), requestPage.getPageSize());
            return sysUserMapper.queryUsers(page, queryParams);
        } catch (IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {
            throw new ServiceException("class:SysUserServiceImpl method:users exception", e);
        }
    }

    @Override
    public CurrentUser loadByUserName(String userName) {
        return sysUserMapper.loadByUserName(userName);
    }

    @Override
    public SysUserVo singleDetail(Long id) {
        SysUserVo sysUserVo = sysUserMapper.singleDetail(id);
        // 用户角色
        SysRoleVo sysRoleVo = sysRoleService.getByUserId(sysUserVo.getId());
        if (!ObjectUtils.isEmpty(sysRoleVo)) {
            sysUserVo.setRoleId(sysRoleVo.getId());
            sysUserVo.setRoleName(sysRoleVo.getRoleName());
        }
        // 用户部门
        List<SysDeptVo> sysDeptVos = sysDeptService.getByUserId(sysUserVo.getId());
        if (!ObjectUtils.isEmpty(sysDeptVos) && sysDeptVos.size() == 2) {
            List<Integer> deptIds = Lists.newArrayList(sysDeptVos.get(0).getId().intValue(), sysDeptVos.get(1).getId().intValue());
            sysUserVo.setDeptIds(deptIds);
            if (sysDeptVos.get(0).getLevel().equals(SystemConstant.DeptLevel.FIRST.getLevel())) {
                sysUserVo.setFirstDeptName(sysDeptVos.get(0).getName());
                sysUserVo.setSecondDeptName(sysDeptVos.get(1).getName());
            } else {
                sysUserVo.setSecondDeptName(sysDeptVos.get(0).getName());
                sysUserVo.setFirstDeptName(sysDeptVos.get(1).getName());
            }
        }
        return sysUserVo;
    }

    /**
     * 新增
     */
    @Transactional(rollbackFor = Exception.class, timeout = 5)
    @Override
    public ServerResponse add(SysUserBO sysUserBO) {
        CurrentUser currentUser = sysUserMapper.loadByUserName(sysUserBO.getUserAccount());
        if (!ObjectUtils.isEmpty(currentUser)) {
            return ServerResponse.error("登录账号已存在");
        }
        SysUser user = sysUserBO.persist();
        int userNum = sysUserMapper.insert(user);
        // 角色菜单关系
        if (userNum > 0) {
            if (!ObjectUtils.isEmpty(sysUserBO.getRoleId())) {
                sysUserRoleMapper.insert(sysUserBO.createUserRole(user.getId()));
            }
            // 用户部门
            if (!ObjectUtils.isEmpty(sysUserBO.getFirstDeptId())) {
                sysUserDeptMapper.insert(sysUserBO.createUserDept(user.getId()));
            }
        }
        return userNum > 0 ? ServerResponse.success(ServiceCodeStatus.SUCCESS) : ServerResponse.error();
    }

    /**
     * 更新
     */
    @Transactional(rollbackFor = Exception.class, timeout = 5)
    @Override
    public boolean update(SysUserBO sysUserBO) {
        SysUser sysUser = sysUserBO.edit();
        int userNum = sysUserMapper.updateById(sysUser);
        if (userNum > 0) {
            // 用户角色
            if (!ObjectUtils.isEmpty(sysUserBO.getRoleId())) {
                sysUserRoleService.updateUserRole(sysUserBO.createUserRole(sysUser.getId()));
            }
            // 用户部门
            if (!ObjectUtils.isEmpty(sysUserBO.getFirstDeptId())) {
                sysUserDeptService.updateUserDept(sysUserBO.createUserDept(sysUser.getId()));
            }
        }
        return userNum > 0;
    }

    @Transactional(rollbackFor = Exception.class, timeout = 5)
    @Override
    public boolean initPwd(SysUserBO sysUserBO) {
        SysUser sysUser = sysUserBO.initPassword();
        return sysUserMapper.updateById(sysUser) > 0;
    }

    /**
     * 修改用户状态
     *
     * @param sysUserBO
     * @return
     */
    @Transactional(rollbackFor = Exception.class, timeout = 5)
    @Override
    public boolean changeStatus(SysUserBO sysUserBO) {
        return sysUserMapper.updateById(sysUserBO.changeStatus()) > 0;
    }

    @Transactional(rollbackFor = Exception.class, timeout = 5)
    @Override
    public boolean delete(List<Long> ids) {
        int num = sysUserMapper.deleteBatchIds(ids);
        if (num > 0) {
            // 删除用户角色关联关系
            sysUserRoleMapper.deleteBachByUserIds(ids);
        }
        return num > 0;
    }

    @Transactional(rollbackFor = Exception.class, timeout = 5)
    @Override
    public boolean changePwd(SysUserBO sysUserBO) {
        SysUser sysUser = sysUserBO.changePassword();
        return sysUserMapper.updateById(sysUser) > 0;
    }

    /**
     * 批量获取
     */
    @Override
    public List<SysUserVo> getByIds(List<Long> ids) {
        return sysUserMapper.queryByIds(ids);
    }

    /**
     * 获取用户二级部门信息
     */
    @Override
    public List<BaseVo> getSecondDeptUserTreeAndIds(List<Long> ids) {
        List<UserDeptDetailVo> userDeptDetailVos = sysUserMapper.queryUserDeptByIds(ids);
        Map<Long, List<UserDeptDetailVo>> map = userDeptDetailVos.stream().collect(Collectors.groupingBy(UserDeptDetailVo::getDeptId));
        List<BaseVo> baseVos = Lists.newArrayList();
        for (Long deptId : map.keySet()) {
            List<UserDeptDetailVo> list = map.get(deptId);
            BaseVo baseVo = new BaseVo();
            baseVo.setLabel(list.get(0).getDeptName());
            baseVo.setValue(list.get(0).getDeptId());
            List<BaseVo> childrens = Lists.newArrayList();
            for (UserDeptDetailVo userDeptDetailVo : list) {
                BaseVo children = new BaseVo();
                children.setParentId(deptId);
                children.setLabel(userDeptDetailVo.getUserName());
                children.setValue(userDeptDetailVo.getUserId());
                childrens.add(children);
            }
            baseVo.setChildren(childrens);
            baseVos.add(baseVo);
        }
        return baseVos;
    }

    /**
     * 获取所有用户
     */
    @Override
    public List<BaseVo> getAll() {
        return sysUserMapper.queryAll();
    }

    /**
     * 获取用户类型
     *
     * @return
     */
    @Override
    public ServerResponse userType() {
        int code = -1;
        SysUserVo sysUserVo = sysUserMapper.singleDetail(SysLoginUserHelper.getLoginUserId());
        if (ObjectUtils.isEmpty(sysUserVo)) {
            return ServerResponse.success(code);
        }
        return ServerResponse.success(sysUserVo.getId());
    }
}
